<template>
  <div class="workflow-trace">
    <!-- 工具栏 -->
    <div class="toolbar">
      <div class="toolbar-left">
        <el-button type="primary" @click="handlePlay" :disabled="isPlaying">
          <el-icon><VideoPlay /></el-icon>
          {{ isPlaying ? '播放中...' : '播放轨迹' }}
        </el-button>
        <el-button @click="handlePause" :disabled="!isPlaying">
          <el-icon><VideoPause /></el-icon>
          暂停
        </el-button>
        <el-button @click="handleStop">
          <el-icon><VideoStop /></el-icon>
          停止
        </el-button>
        <el-button @click="handleReset">
          <el-icon><Refresh /></el-icon>
          重置
        </el-button>
      </div>
      <div class="toolbar-right">
        <el-slider
          v-model="playProgress"
          :max="100"
          :show-tooltip="false"
          @change="handleProgressChange"
          style="width: 200px; margin-right: 16px;"
        />
        <span class="progress-text">{{ currentStep }}/{{ totalSteps }}</span>
      </div>
    </div>

    <!-- 轨迹信息面板 -->
    <div class="trace-panel">
      <div class="panel-title">轨迹信息</div>
      <div class="trace-list">
        <div 
          v-for="(trace, index) in traceData" 
          :key="trace.id"
          class="trace-item"
          :class="{ 
            'active': index === currentStep - 1,
            'completed': index < currentStep - 1,
            'pending': index > currentStep - 1
          }"
          @click="handleTraceClick(index)"
        >
          <div class="trace-step">{{ index + 1 }}</div>
          <div class="trace-content">
            <div class="trace-node">{{ trace.nodeName }}</div>
            <div class="trace-action">{{ getActionLabel(trace.action) }}</div>
            <div class="trace-user">{{ trace.userName }}</div>
            <div class="trace-time">{{ formatTime(trace.timestamp) }}</div>
            <div v-if="trace.comment" class="trace-comment">{{ trace.comment }}</div>
          </div>
          <div class="trace-status">
            <el-icon v-if="index < currentStep - 1" color="#67c23a">
              <CircleCheck />
            </el-icon>
            <el-icon v-else-if="index === currentStep - 1" color="#409eff">
              <Loading />
            </el-icon>
            <el-icon v-else color="#c0c4cc">
              <Clock />
            </el-icon>
          </div>
        </div>
      </div>
    </div>

    <!-- 画布区域 -->
    <div class="canvas-container">
      <div ref="containerRef" class="logicflow-container"></div>
      
      <!-- 播放控制覆盖层 -->
      <div v-if="isPlaying" class="play-overlay">
        <div class="play-indicator">
          <el-icon class="play-icon">
            <Loading />
          </el-icon>
          <span>正在播放轨迹...</span>
        </div>
      </div>
    </div>

    <!-- 变量面板 -->
    <div class="variable-panel" v-if="currentVariables">
      <div class="panel-title">当前变量</div>
      <div class="variable-list">
        <div 
          v-for="(value, key) in currentVariables" 
          :key="key"
          class="variable-item"
        >
          <span class="variable-key">{{ key }}:</span>
          <span class="variable-value">{{ JSON.stringify(value) }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, nextTick, computed } from 'vue';
import { ElMessage } from 'element-plus';
import { 
  VideoPlay, 
  VideoPause, 
  VideoStop, 
  Refresh,
  CircleCheck,
  Loading,
  Clock
} from '@element-plus/icons-vue';
import LogicFlow from '@logicflow/core';
import '@logicflow/core/dist/style/index.css';
import { 
  getWorkflowGraphData,
  getWorkflowTrace 
} from '@/api/workflow';
import type { WorkflowGraphData, WorkflowTrace as WorkflowTraceType } from '@/api/workflow/WorkflowModel';

// Props
const props = defineProps<{
  instanceId: number;
}>();

// Emits
const emit = defineEmits<{
  close: [];
}>();

// 响应式数据
const containerRef = ref<HTMLElement>();
const lf = ref<LogicFlow>();
const traceData = ref<WorkflowTraceType[]>([]);
const isPlaying = ref(false);
const currentStep = ref(0);
const playProgress = ref(0);
const playTimer = ref<NodeJS.Timeout | null>(null);
const currentVariables = ref<Record<string, any> | null>(null);

// 计算属性
const totalSteps = computed(() => traceData.value.length);

// 动作标签映射
const actionLabels = {
  start: '开始',
  complete: '完成',
  skip: '跳过',
  reject: '拒绝'
};

// 获取动作标签
const getActionLabel = (action: string) => {
  return actionLabels[action as keyof typeof actionLabels] || action;
};

// 格式化时间
const formatTime = (timestamp: string) => {
  return new Date(timestamp).toLocaleString();
};

// 初始化LogicFlow
const initLogicFlow = () => {
  if (!containerRef.value) return;

  lf.value = new LogicFlow({
    container: containerRef.value,
    grid: true,
    disabledTools: ['zoom', 'pan'],
    style: {
      rect: {
        rx: 5,
        ry: 5,
        strokeWidth: 2
      },
      circle: {
        r: 20,
        strokeWidth: 2
      },
      diamond: {
        rx: 10,
        ry: 10,
        strokeWidth: 2
      }
    }
  });

  // 注册自定义节点
  registerCustomNodes();

  // 加载工作流数据
  loadWorkflowData();
};

// 注册自定义节点
const registerCustomNodes = () => {
  if (!lf.value) return;

  // 开始节点
  lf.value.register({
    type: 'start',
    view: 'circle',
    model: 'circle',
    text: '开始'
  });

  // 结束节点
  lf.value.register({
    type: 'end',
    view: 'circle',
    model: 'circle',
    text: '结束'
  });

  // 用户任务节点
  lf.value.register({
    type: 'userTask',
    view: 'rect',
    model: 'rect',
    text: '用户任务'
  });

  // 服务任务节点
  lf.value.register({
    type: 'serviceTask',
    view: 'rect',
    model: 'rect',
    text: '服务任务'
  });

  // 网关节点
  lf.value.register({
    type: 'gateway',
    view: 'diamond',
    model: 'diamond',
    text: '网关'
  });
};

// 加载工作流数据
const loadWorkflowData = async () => {
  try {
    // 这里需要根据实例ID获取对应的工作流ID
    // 假设从props中传入workflowId
    const workflowId = 1; // 实际应该从实例数据中获取
    const response = await getWorkflowGraphData(workflowId);
    const graphData = response.data;
    
    if (graphData && lf.value) {
      lf.value.render(graphData);
    }
  } catch (error) {
    ElMessage.error('加载工作流数据失败');
  }
};

// 加载轨迹数据
const loadTraceData = async () => {
  try {
    const response = await getWorkflowTrace(props.instanceId);
    traceData.value = response.data || [];
    
    if (traceData.value.length > 0) {
      // 初始化节点状态
      initNodeStates();
    }
  } catch (error) {
    ElMessage.error('加载轨迹数据失败');
  }
};

// 初始化节点状态
const initNodeStates = () => {
  if (!lf.value) return;

  const nodes = lf.value.getGraphData().nodes;
  nodes.forEach(node => {
    const nodeModel = lf.value!.getNodeModelById(node.id);
    if (nodeModel) {
      // 设置初始状态为待处理
      nodeModel.setProperties({
        ...nodeModel.properties,
        status: 'pending'
      });
    }
  });
};

// 播放轨迹
const handlePlay = () => {
  if (traceData.value.length === 0) {
    ElMessage.warning('没有轨迹数据');
    return;
  }

  isPlaying.value = true;
  currentStep.value = 1;
  
  // 开始播放
  playStep();
};

// 播放步骤
const playStep = () => {
  if (currentStep.value > traceData.value.length) {
    handleStop();
    return;
  }

  const trace = traceData.value[currentStep.value - 1];
  if (trace) {
    // 高亮当前节点
    highlightNode(trace.nodeId, trace.action);
    
    // 更新变量
    if (trace.variables) {
      currentVariables.value = trace.variables;
    }
    
    // 更新进度
    playProgress.value = (currentStep.value / traceData.value.length) * 100;
    
    // 延迟播放下一步
    playTimer.value = setTimeout(() => {
      currentStep.value++;
      playStep();
    }, 2000); // 2秒间隔
  }
};

// 高亮节点
const highlightNode = (nodeId: string, action: string) => {
  if (!lf.value) return;

  const nodeModel = lf.value.getNodeModelById(nodeId);
  if (nodeModel) {
    // 根据动作设置不同的样式
    let color = '#409eff'; // 默认蓝色
    switch (action) {
      case 'start':
        color = '#67c23a'; // 绿色
        break;
      case 'complete':
        color = '#67c23a'; // 绿色
        break;
      case 'skip':
        color = '#e6a23c'; // 橙色
        break;
      case 'reject':
        color = '#f56c6c'; // 红色
        break;
    }
    
    nodeModel.setProperties({
      ...nodeModel.properties,
      status: action,
      highlightColor: color
    });
  }
};

// 暂停播放
const handlePause = () => {
  isPlaying.value = false;
  if (playTimer.value) {
    clearTimeout(playTimer.value);
    playTimer.value = null;
  }
};

// 停止播放
const handleStop = () => {
  isPlaying.value = false;
  currentStep.value = 0;
  playProgress.value = 0;
  
  if (playTimer.value) {
    clearTimeout(playTimer.value);
    playTimer.value = null;
  }
  
  // 重置所有节点状态
  resetNodeStates();
};

// 重置
const handleReset = () => {
  handleStop();
  currentVariables.value = null;
  initNodeStates();
};

// 重置节点状态
const resetNodeStates = () => {
  if (!lf.value) return;

  const nodes = lf.value.getGraphData().nodes;
  nodes.forEach(node => {
    const nodeModel = lf.value!.getNodeModelById(node.id);
    if (nodeModel) {
      nodeModel.setProperties({
        ...nodeModel.properties,
        status: 'pending',
        highlightColor: undefined
      });
    }
  });
};

// 进度变化
const handleProgressChange = (value: number) => {
  if (isPlaying.value) return;
  
  const step = Math.round((value / 100) * traceData.value.length);
  currentStep.value = Math.max(1, step);
  
  // 更新到指定步骤
  updateToStep(currentStep.value);
};

// 更新到指定步骤
const updateToStep = (step: number) => {
  if (step > traceData.value.length) return;
  
  // 重置所有节点
  resetNodeStates();
  
  // 逐步高亮到指定步骤
  for (let i = 0; i < step; i++) {
    const trace = traceData.value[i];
    if (trace) {
      highlightNode(trace.nodeId, trace.action);
    }
  }
  
  // 更新变量
  if (step > 0) {
    const trace = traceData.value[step - 1];
    if (trace && trace.variables) {
      currentVariables.value = trace.variables;
    }
  } else {
    currentVariables.value = null;
  }
};

// 轨迹项点击
const handleTraceClick = (index: number) => {
  if (isPlaying.value) return;
  
  currentStep.value = index + 1;
  playProgress.value = ((index + 1) / traceData.value.length) * 100;
  updateToStep(currentStep.value);
};

// 生命周期
onMounted(() => {
  nextTick(() => {
    initLogicFlow();
    loadTraceData();
  });
});

onUnmounted(() => {
  if (playTimer.value) {
    clearTimeout(playTimer.value);
  }
  if (lf.value) {
    lf.value.destroy();
  }
});
</script>

<style scoped>
.workflow-trace {
  display: flex;
  height: 100%;
  background: #f5f5f5;
}

.toolbar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 50px;
  background: white;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  z-index: 1000;
}

.toolbar-left,
.toolbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.progress-text {
  font-size: 14px;
  color: #606266;
  min-width: 60px;
}

.trace-panel {
  width: 300px;
  background: white;
  border-right: 1px solid #e4e7ed;
  margin-top: 50px;
  height: calc(100% - 50px);
  overflow-y: auto;
}

.panel-title {
  padding: 16px;
  font-weight: bold;
  border-bottom: 1px solid #e4e7ed;
  background: #fafafa;
}

.trace-list {
  padding: 16px;
}

.trace-item {
  display: flex;
  align-items: flex-start;
  padding: 12px;
  margin-bottom: 8px;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s;
  background: white;
}

.trace-item:hover {
  border-color: #409eff;
  box-shadow: 0 2px 4px rgba(64, 158, 255, 0.1);
}

.trace-item.active {
  border-color: #409eff;
  background: #f0f9ff;
}

.trace-item.completed {
  border-color: #67c23a;
  background: #f0f9f0;
}

.trace-item.pending {
  border-color: #e4e7ed;
  background: #fafafa;
}

.trace-step {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #e4e7ed;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: bold;
  margin-right: 12px;
  flex-shrink: 0;
}

.trace-item.active .trace-step {
  background: #409eff;
}

.trace-item.completed .trace-step {
  background: #67c23a;
}

.trace-content {
  flex: 1;
  min-width: 0;
}

.trace-node {
  font-weight: bold;
  color: #303133;
  margin-bottom: 4px;
}

.trace-action {
  font-size: 12px;
  color: #606266;
  margin-bottom: 2px;
}

.trace-user {
  font-size: 12px;
  color: #909399;
  margin-bottom: 2px;
}

.trace-time {
  font-size: 12px;
  color: #c0c4cc;
  margin-bottom: 4px;
}

.trace-comment {
  font-size: 12px;
  color: #606266;
  background: #f5f7fa;
  padding: 4px 8px;
  border-radius: 4px;
  margin-top: 4px;
}

.trace-status {
  display: flex;
  align-items: center;
  margin-left: 8px;
  flex-shrink: 0;
}

.canvas-container {
  flex: 1;
  margin-top: 50px;
  position: relative;
}

.logicflow-container {
  width: 100%;
  height: 100%;
  background: white;
}

.play-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}

.play-indicator {
  display: flex;
  align-items: center;
  gap: 8px;
  background: white;
  padding: 12px 24px;
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.play-icon {
  animation: rotate 1s linear infinite;
}

@keyframes rotate {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.variable-panel {
  width: 250px;
  background: white;
  border-left: 1px solid #e4e7ed;
  margin-top: 50px;
  height: calc(100% - 50px);
  overflow-y: auto;
}

.variable-list {
  padding: 16px;
}

.variable-item {
  display: flex;
  flex-direction: column;
  padding: 8px;
  margin-bottom: 8px;
  background: #f5f7fa;
  border-radius: 4px;
}

.variable-key {
  font-weight: bold;
  color: #303133;
  margin-bottom: 4px;
}

.variable-value {
  font-size: 12px;
  color: #606266;
  word-break: break-all;
}
</style>

